#include "shell.h"
#include "parse.h"
#include <string.h>

int parse(t_CmdLine *cmdLine, char *line)
{
	int i, j, retVal, flag;
	char *cmd;
	t_CmdLine *cmdLinePtr;

	i = 0;
	retVal = 0;
	flag = 0;
	cmdLinePtr = cmdLine;
	while (line[i] != '\0')
	{
		cmd = malloc(sizeof(char)*4096);
		if (flag == 0)
		{
			flag = 1;
			cmdLinePtr->cmd = NULL;
			cmdLinePtr->next = NULL;
			cmdLine = cmdLinePtr;
		}
		else
		{
			cmdLinePtr->next = malloc(sizeof(t_CmdLine));
			cmdLinePtr = cmdLinePtr->next;
			cmdLinePtr->next = NULL;
			cmdLinePtr->cmd = NULL;
		}
		j = 0;
		while (line[i] != '\0' && line[i] != '|')
		{
			cmd[j] = line[i];
			i++;
			j++;
		}
		if (line[i] == '|')
			i++;
		cmd[j] = '\0';
		cmdLinePtr->cmd = malloc(sizeof(t_Command));
		retVal = parse_singleCmd(cmdLinePtr->cmd, cmd);
		if (retVal == -1)
			return retVal;
		free(cmd);
	}

	//test
/*	while (cmdLine)
	{
		printf("[parse: %s]\n", cmdLine->cmd->cmd);
		cmdLine = cmdLine->next;
	}
*/	return retVal;
}

/* 
 *  return value indicates the parsing results
 * -1 means systax error
 */
int parse_singleCmd(t_Command *tmpCmd, char *call)
{
	int i, j;
	int callNameFlag;
	t_file *tmpin, *inptr;
	t_file *tmpout, *outptr;
	t_file *tmperr, *errptr;
	t_args *tmparg, *argptr;
	char *str;
	t_Command *res;

	//Initialization
	i = 0;
	callNameFlag = 0;
	tmpin = tmpCmd->inFile = NULL;
	tmpout = tmpCmd->outFile = NULL;
	tmparg = tmpCmd->arguments = NULL;
	tmperr = tmpCmd->errMsg = NULL;
	inptr = NULL;
	outptr = NULL;
	errptr = NULL;
	argptr = NULL;
	str = NULL;
	res = malloc(sizeof(t_Command));
	res->cmd = NULL;
	res->arguments = NULL;
	res->inFile = NULL;
	res->outFile = NULL;
	res->errMsg = NULL;

	while (call[i] != '\0')
	{
		i = skipSpace(call, i);
		//inFile
		if (call[i] == '<')
		{
			j = 0;
			str = malloc(sizeof(char)*4096);
			i++;
			i = skipSpace(call, i);
			if (call[i] == '\0')
			{
				if (tmpin)
					free(tmpin);
				if (tmpout)
					free(tmpout);
				if (tmperr)
					free(tmperr);
				if (inptr)
					free(inptr);
				if (outptr)
					free(outptr);
				if (errptr)
					free(errptr);
				if (tmparg)
					free(tmparg);
				if (argptr)
					free(argptr);
				if (str)
					free(str);
				//Syntax error
				return -1;
			}
			while (call[i] != '\0' && call[i] != '\t' && call[i] != ' ')
			{
				str[j] = call[i];
				j++;
				i++;
			}
			str[j] = '\0';
			if (tmpin == NULL)
			{
				tmpCmd->inFile = malloc(sizeof(t_file));
				tmpin = tmpCmd->inFile;
				tmpin->next = NULL;
				inptr = tmpin;
				inptr->fileName = malloc(sizeof(char)*(j+1));
				strncpy(inptr->fileName, &str[0], j+1);
				free(str);
				continue;
			}
			else
			{
				inptr->next = malloc(sizeof(t_file));
				inptr = inptr->next;
				inptr->next = NULL;
				inptr->fileName = malloc(sizeof(char)*j);
				strncpy(inptr->fileName, &str[0], j+1);
				free(str);
				continue;
			}
		}

		//outFile
		if (call[i] == '>')
		{
			j = 0;
			str = malloc(sizeof(char)*4096);
			i++;
			i = skipSpace(call, i);
			if (call[i] == '\0')
			{
				if (tmpin)
					free(tmpin);
				if (tmpout)
					free(tmpout);
				if (tmperr)
					free(tmperr);
				if (inptr)
					free(inptr);
				if (outptr)
					free(outptr);
				if (errptr)
					free(errptr);
				if (tmparg)
					free(tmparg);
				if (argptr)
					free(argptr);
				if (str)
					free(str);
				//Syntax error
				return -1;
			}
			while (call[i] != '\0' && call[i] != '\t' && call[i] != ' ')
			{
				str[j] = call[i];
				j++;
				i++;
			}
			str[j] = '\0';
			if (tmpout == NULL)
			{
				tmpCmd->outFile = malloc(sizeof(t_file));
				tmpout = tmpCmd->outFile;
				tmpout->next = NULL;
				outptr = tmpout;
				outptr->fileName = malloc(sizeof(char)*(j+1));
				strncpy(outptr->fileName, &str[0], j+1);
				free(str);
				continue;
			}
			else
			{
				outptr->next = malloc(sizeof(t_file));
				outptr = outptr->next;
				outptr->next = NULL;
				outptr->fileName = malloc(sizeof(char)*(j+1));
				strncpy(outptr->fileName, &str[0], j+1);
				free(str);
				continue;
			}
		}
		//errMsg
		if (call[i] == '2')
		{
			if (call[i+1] != '\0' && call[i+1] == '>')
			{
				i = i + 2;
				j = 0;
				str = malloc(sizeof(char)*4096);
				i = skipSpace(call, i);
				if (call[i] == '\0')
				{
					if (tmpin)
						free(tmpin);
					if (tmpout)
						free(tmpout);
					if (tmperr)
						free(tmperr);
					if (inptr)
						free(inptr);
					if (outptr)
						free(outptr);
					if (errptr)
						free(errptr);
					if (tmparg)
						free(tmparg);
					if (argptr)
						free(argptr);
					if (str)
						free(str);
					//Syntax error
					return -1;
				}
				while (call[i] != '\0' && call[i] != '\t' && call[i] != ' ')
				{
					str[j] = call[i];
					j++;
					i++;
				}
				str[j] = '\0';
				if (tmperr == NULL)
				{
					tmpCmd->errMsg = malloc(sizeof(t_file));
					tmperr = tmpCmd->errMsg;
					tmperr->next = NULL;
					errptr = tmperr;
					errptr->fileName = malloc(sizeof(char)*j);
					strncpy(errptr->fileName, &str[0], j+1);
					free(str);
					continue;
				}
				else
				{
					errptr->next = malloc(sizeof(t_file));
					errptr = errptr->next;
					errptr->next = NULL;
					errptr->fileName = malloc(sizeof(char)*j);
					strncpy(errptr->fileName, &str[0], j+1);
					free(str);
					continue;
				}
			}
		}
		//name of the command
		if (callNameFlag == 0)
		{
			j = 0;
			str = malloc(sizeof(char)*4096);
			while (call[i] != '\0' && call[i] != '\t' && call[i] != ' ')
			{
				str[j] = call[i];
				i++;
				j++;
			}
			str[j] = '\0';
			tmpCmd->cmd = malloc(sizeof(char)*j);
			strncpy(tmpCmd->cmd, &str[0], j+1);
			free(str);
			callNameFlag = 1;
			continue;
		}
		else
		//arguments
		{
			j = 0;
			str = malloc(sizeof(char)*4096);
			while (call[i] != '\0' && call[i] != ' ' && call[i] != '\t')
			{
				str[j] = call[i];
				i++;
				j++;
			}
			str[j] = '\0';
			if (j == 0)
			{
				free(str);
				continue;
			}
			if (tmparg == NULL)
			{
				tmpCmd->arguments = malloc(sizeof(t_args));
				tmparg = tmpCmd->arguments;
				argptr = tmparg;
				argptr->next = NULL;
				argptr->arg = malloc(sizeof(char)*(j+1));
				strncpy(argptr->arg, &str[0], j+1);
				free(str);
				continue;
			}
			else
			{
				argptr->next = malloc(sizeof(t_args));
				argptr = argptr->next;
				argptr->next = NULL;
				argptr->arg = malloc(sizeof(char)*(j+1));
				strncpy(argptr->arg, &str[0], j+1);
				free(str);
				continue;
			}
		}
	}

	res->arguments = tmparg;
	res->inFile = tmpin;
	res->outFile = tmpout;
	res->errMsg = tmperr;

	//test
/*	printf("[cmd: %s]\n", tmpCmd->cmd);

	t_args *testarg;
	testarg = res->arguments;
	while (testarg != NULL && testarg->arg != NULL)
	{
		printf("[args: %s]\n", testarg->arg);
		testarg = testarg->next;
	}

	t_file *tmp;
	tmp = res->inFile;
	while (tmp != NULL && tmp->fileName != NULL)
	{
		printf("[inFile: %s]\n", tmp->fileName);
		tmp = tmp->next;
	}
	
	tmp = res->outFile;
	while (tmp != NULL && tmp->fileName != NULL)
	{
		printf("[outFile: %s]\n", tmp->fileName);
		tmp = tmp->next;
	}
	
	tmp = res->errMsg;
	while (tmp != NULL && tmp->fileName != NULL)
	{
		printf("[errMsg: %s]\n", tmp->fileName);
		tmp = tmp->next;
	}
*/
	return 0;
}

int skipSpace(char *line, int index)
{
	while (line[index] != '\0')
	{
		if (line[index] != ' ' && line[index] != '\t')
			return index;
		else
			index++;
	}
	return index;
}
